namespace BadHabit.Factory
{
    using System;
    using System.Diagnostics;
    using System.IO;

    public partial class FactoryLogic
    {
        #region TableAdapters

        private Data.ProjectDataSetTableAdapters.ProjectTableAdapter projectTA = new BadHabit.Factory.Data.ProjectDataSetTableAdapters.ProjectTableAdapter();

        private Data.ProjectDataSetTableAdapters.ProjectRoleTableAdapter projectRoleTA = new BadHabit.Factory.Data.ProjectDataSetTableAdapters.ProjectRoleTableAdapter();

        private Data.ProjectDataSetTableAdapters.BacklogItemTableAdapter backlogItemTA = new BadHabit.Factory.Data.ProjectDataSetTableAdapters.BacklogItemTableAdapter();
        private Data.ProjectDataSetTableAdapters.BacklogItemUnitTableAdapter backlogItemUnitTA = new BadHabit.Factory.Data.ProjectDataSetTableAdapters.BacklogItemUnitTableAdapter();
        private Data.ProjectDataSetTableAdapters.BacklogItemHoursTableAdapter backlogItemHoursTA = new BadHabit.Factory.Data.ProjectDataSetTableAdapters.BacklogItemHoursTableAdapter();

        private Data.ProjectDataSetTableAdapters.SprintTableAdapter sprintTA = new BadHabit.Factory.Data.ProjectDataSetTableAdapters.SprintTableAdapter();
        private Data.ProjectDataSetTableAdapters.SprintCodeVersionTableAdapter sprintCodeVersionTA = new BadHabit.Factory.Data.ProjectDataSetTableAdapters.SprintCodeVersionTableAdapter();

        private Data.ProjectDataSetTableAdapters.QueriesTableAdapter queriesTA = new BadHabit.Factory.Data.ProjectDataSetTableAdapters.QueriesTableAdapter();

        // Proposals TAs
        private Data.ProjectDataSetTableAdapters.ProposalTableAdapter proposalTA = new BadHabit.Factory.Data.ProjectDataSetTableAdapters.ProposalTableAdapter();
        private Data.ProjectDataSetTableAdapters.ProposalApprovedTableAdapter proposalApprovedTA = new BadHabit.Factory.Data.ProjectDataSetTableAdapters.ProposalApprovedTableAdapter();
        private Data.ProjectDataSetTableAdapters.ProposalItemTableAdapter proposalItemTA = new BadHabit.Factory.Data.ProjectDataSetTableAdapters.ProposalItemTableAdapter();
        private Data.ProjectDataSetTableAdapters.ProposalObservationTableAdapter proposalObservationsTA = new BadHabit.Factory.Data.ProjectDataSetTableAdapters.ProposalObservationTableAdapter();
        private Data.ProjectDataSetTableAdapters.ProposalFixedCostItemTableAdapter proposalFixedCostItemTA = new BadHabit.Factory.Data.ProjectDataSetTableAdapters.ProposalFixedCostItemTableAdapter();
        private Data.ProjectDataSetTableAdapters.ProjectPaymentTableAdapter projectPaymentTA = new BadHabit.Factory.Data.ProjectDataSetTableAdapters.ProjectPaymentTableAdapter();

        private Data.ProjectPerformanceDataSetTableAdapters.ProjectPerformanceTableAdapter performanceTA = new BadHabit.Factory.Data.ProjectPerformanceDataSetTableAdapters.ProjectPerformanceTableAdapter();

        private Data.ProjectDataSetTableAdapters.RiskTableAdapter riskTA = new BadHabit.Factory.Data.ProjectDataSetTableAdapters.RiskTableAdapter();

        #endregion

        private const string APPLICATION_LOGNAME = "Factory Server";

        private static string serverFilePath;
        private static string serverUrl;

        private static FactoryLogic currentFactory = null;

        public static void CreateFactory(string serverFilePath, string serverUrl)
        {
            if (currentFactory != null)
            {
                return;
            }

            currentFactory = new FactoryLogic(serverFilePath, serverUrl);
        }

        public static FactoryLogic Current
        {
            get
            {
                if (currentFactory == null)
                {
                    throw new Exception("Factory was not created.");
                }

                return currentFactory;
            }
        }

        public string UserCulture
        {
            get;
            set;
        }

        /// <summary>
        /// Creates a factory at the given server path.
        /// </summary>
        /// <param name="serverPath">The server url</param>
        private FactoryLogic(string serverFilePath, string serverUrl)
        {
            FactoryLogic.serverFilePath = serverFilePath;
            FactoryLogic.serverUrl = serverUrl;

            this.LoadTeamMembers();

            this.proposalObservationsTA.ClearBeforeFill = false;
            this.proposalItemTA.ClearBeforeFill = false;
            this.proposalFixedCostItemTA.ClearBeforeFill = false;
        }

        public static string ServerUrl
        {
            get
            {
                return serverUrl;
            }
        }

        public static string ServerPath
        {
            get
            {
                return serverFilePath;
            }
        }

        /// <summary>
        /// Approves the proposal.
        /// </summary>
        /// <param name="user">User approving the proposal</param>
        /// <param name="project">Project that should be approved</param>
        public Data.ProjectDataSet ApproveProposal(Data.ProjectDataSet project, string proposalUId, out string alertMessage)
        {
            Data.ProjectDataSet.ProposalRow proposal = project.Proposal.FindByProposalUId(proposalUId);
            if (proposal == null)
            {
                throw new Exception("Could not find the proposal to approve it.");
            }

            // Set approval date and status
            proposal.ApprovalDate = DateTime.Now;
            this.SetProposalStatus(proposal, project.Project[0], ProposalStatus.PROPOSAL_APPROVED);

            this.SaveProposalApprovedXAML(proposal);

            return this.PrepareToSaveProject(project, out alertMessage);
        }

        private void SaveProposalApprovedXAML(Data.ProjectDataSet.ProposalRow proposal)
        {
            Reports.ProposalReport report = new Reports.ProposalReport(this, proposal.ProposalUId);

            Data.ProjectDataSet dataset = proposal.Table.DataSet as Data.ProjectDataSet;

            string proposalXaml = report.GenerateFlowDocumentXAML(dataset, proposal.TemplateName);
            dataset.ProposalApproved.AddProposalApprovedRow(proposal, proposal.ProjectUId, proposalXaml);
        }

        public string RetriveApprovedProposalXaml(string proposalUId)
        {
            Data.ProjectDataSet dataset = new BadHabit.Factory.Data.ProjectDataSet();
            dataset.EnforceConstraints = false;
            this.proposalApprovedTA.FillByProposalUId(dataset.ProposalApproved, proposalUId);
            if (dataset.ProposalApproved.Count == 0)
            {
                return null;
            }

            return dataset.ProposalApproved[0].ProposalXAML;
        }

        /// <summary>
        /// Rejects a Proposal.
        /// </summary>
        /// <param name="user">User sending the proposal</param>
        /// <param name="project">Project</param>
        public Data.ProjectDataSet RejectProposal(Data.ProjectDataSet project, string proposalUId, out string alertMesssage)
        {
            Data.ProjectDataSet.ProposalRow proposal = project.Proposal.FindByProposalUId(proposalUId);
            if (proposal == null)
            {
                throw new Exception("Could not find the proposal to reject it.");
            }

            proposal.ApprovalDate = DateTime.Now;
            this.SetProposalStatus(proposal, project.Project[0], ProposalStatus.PROPOSAL_REJECTED);

            this.SaveProposalApprovedXAML(proposal);

            return this.PrepareToSaveProject(project, out alertMesssage);
        }

        /// <summary>
        /// Update the proposal and the project with the given status.
        /// Note that the project status is not always equal to the proposal, it
        /// is calculed based on all proposal status.
        /// </summary>
        /// <param name="proposal">The proposal row</param>
        /// <param name="status">The new status</param>
        private void SetProposalStatus(Data.ProjectDataSet.ProposalRow proposal, Data.ProjectDataSet.ProjectRow project, ProposalStatus status)
        {
            Data.ProjectDataSet ds = (Data.ProjectDataSet)proposal.Table.DataSet;

            if (project == null)
            {
                throw new Exception("Could not find the project of the proposal");
            }

            // set the proposal status
            proposal.Status = (short)status;

            if (project.Status == (short)ProjectStatus.PROJECT_STARTED)
            {
                return;
            }

            // Now set the project status
            int totalCount = ds.Proposal.Rows.Count;
            int waintingCount = Int32.Parse(ds.Proposal.Compute("count(proposalUId)", "Status=" + (short)ProposalStatus.PROPOSAL_WAITING).ToString());
            int approvedCount = Int32.Parse(ds.Proposal.Compute("count(proposalUId)", "Status=" + (short)ProposalStatus.PROPOSAL_APPROVED).ToString());
            int rejectCount = Int32.Parse(ds.Proposal.Compute("count(proposalUId)", "Status=" + (short)ProposalStatus.PROPOSAL_REJECTED).ToString());

            // if all the proposal were rejected, so is the project
            if (rejectCount == totalCount)
            {
                project.Status = (short)ProjectStatus.PROPOSAL_REJECTED;
            }

            // if is there at least one waiting, so is the project
            if (waintingCount > 0)
            {
                project.Status = (short)ProjectStatus.PROPOSAL_WAITING;
            }

            // if is there no wainting, but at least one approved, so is approved the project
            if (approvedCount > 0)
            {
                project.Status = (short)ProjectStatus.PROPOSAL_APPROVED;
            }
        }

        private void RunCreateHook(Data.ProjectDataSet project)
        {
            string hookPath = ServerPath + @"\App_Data\ProjectTemplates\" + project.Project[0].Category + @"\Hooks\CreateProject.bat";
            string args = "\"" + project.Project[0].ClientName + "\" \"" + project.Project[0].ProjectName + "\" \"";

            System.Diagnostics.ProcessStartInfo psi = new ProcessStartInfo(hookPath, args);

            psi.CreateNoWindow = true;
            psi.UseShellExecute = true;

            System.Diagnostics.Process p = new Process();
            p.StartInfo = psi;
            try
            {
                p.Start();
            }
            catch (Exception ex)
            {
                LogError(ex);
                return;
            }

            p.WaitForExit();

            if (p.ExitCode != 0)
            {
                LogError(null, "CreateProject.Bat exit with error " + p.ExitCode);
            }
        }

        /// <summary>
        /// Need to make sure that only the VerifiedBy and VerifiedDate columns from
        /// BacklogItem table is changed when is a Quality Assurance Role that is saving.
        /// </summary>
        /// <param name="project"></param>
        /// <returns></returns>
        private Data.ProjectDataSet RestrictQualityAssuranceSave(Data.ProjectDataSet project)
        {
            // just backlog items
            Data.ProjectDataSet dataset = new BadHabit.Factory.Data.ProjectDataSet();
            dataset.Merge(project.Project);
            dataset.Merge(project.BacklogItem);

            dataset.Project[0].RejectChanges();

            // revert all columns to original itens, except the verified By and Date
            for (int i = 0; i < dataset.BacklogItem.Count; i++)
            {
                foreach (System.Data.DataColumn c in dataset.BacklogItem.Columns)
                {
                    if (!c.Equals(dataset.BacklogItem.VerifiedByColumn) && !c.Equals(dataset.BacklogItem.VerifiedDateColumn))
                    {
                        dataset.BacklogItem[i][c.ColumnName] = dataset.BacklogItem[i][c.ColumnName, System.Data.DataRowVersion.Original];
                    }
                }
            }

            return dataset;
        }

        /// <summary>
        /// Saves the project.
        /// </summary>
        /// <param name="project">project to be saved</param>
        public Data.ProjectDataSet PrepareToSaveProject(Data.ProjectDataSet project, out string alertMessage)
        {
            alertMessage = null;

            if (!CurrentTeamMemberPrincipal.IsInRole(TeamRoles.SCRUM_MASTER.ToString()))
            {
                project = this.RestrictQualityAssuranceSave(project);
            }

            if (project.Project.Count > 0)
            {
                // if it's a new project
                if (project.Project[0].RowState == System.Data.DataRowState.Added)
                {
                    project.Project[0].Status = (short)ProjectStatus.PROPOSAL_CREATION; // sets project status
                    project.Project[0].ProjectOwner = CurrentTeamMember;
                    if (project.Project[0].IsProjectDocBaseNull())
                    {
                        project.Project[0].ProjectDocBase = this.CalcsProjectDocBasePath(project);
                    }

                    this.RunCreateHook(project);
                }
            }

            // save its now
            Data.ProjectDataSet savedProject = null;
            try
            {
                savedProject = this.SaveProject(project);
            }
            catch (System.Data.DBConcurrencyException)
            {
                alertMessage = "CONCURRENCY_SAVE_ERROR";
                return null;
            }
            catch (System.Data.SqlClient.SqlException sqlEx)
            {
                if (sqlEx.Number == 547)
                {
                    alertMessage = "CONSTRAINT_SAVE_ERROR";
                    return null;
                }

                throw sqlEx;
            }

            this.SendSaveProjectEmails(savedProject);

            return savedProject;
        }

        public void SendSaveProjectEmails(Data.ProjectDataSet project)
        {
            if (project.Project.Count == 0)
            {
                return;
            }

            ProjectEmailMessage msg = new ProjectEmailMessage(project.Project[0].ProjectUId, ServerPath, ServerUrl);

            // if project has changed its status
            if (project.Project[0].RowState.Equals(System.Data.DataRowState.Added) ||
                !project.Project[0].Status.Equals(project.Project[0]["Status", System.Data.DataRowVersion.Original]))
            {
                try
                {
                    msg.SendStatusChangeNotification();
                }
                catch (Exception ex)
                {
                    LogError(ex);
                }
            }

            // if project has changed its baseline
            if (project.Project[0].RowState.Equals(System.Data.DataRowState.Added) ||
                !project.Project[0].Baseline.Equals(project.Project[0]["Baseline", System.Data.DataRowVersion.Original]))
            {
                try
                {
                    msg.SendNewPlanNotification();
                }
                catch (Exception ex)
                {
                    LogError(ex);
                }
            }

            // if project has new members
            Data.ProjectDataSet.ProjectRoleRow[] newMembers = (Data.ProjectDataSet.ProjectRoleRow[])project.ProjectRole.Select(string.Empty, string.Empty, System.Data.DataViewRowState.Added);
            if (project.Project[0].RowState.Equals(System.Data.DataRowState.Added) ||
                newMembers.Length > 0)
            {
                try
                {
                    msg.SendNewMemberNotification(newMembers);
                }
                catch (Exception ex)
                {
                    LogError(ex);
                }
            }
        }

        /// <summary>
        /// Calcs the project doc base for a given project.
        /// </summary>
        /// <param name="project">Project</param>
        /// <returns>doc base path</returns>
        public string CalcsProjectDocBasePath(Data.ProjectDataSet project)
        {
            return Properties.Settings.Default.DocumentRepositoryPath + "\\" + project.Project[0].ClientName + "\\" + project.Project[0].ProjectName;
        }

        /// <summary>
        /// Retrives the project template list that are saved at the root path.
        /// </summary>
        /// <param name="rootPath">Root Path</param>
        /// <returns>Name of the project templates</returns>
        public string[] RetriveProjectTemplateList(string rootPath)
        {
            string[] list = System.IO.Directory.GetDirectories(rootPath);
            for (int i = 0; i < list.Length; i++)
            {
                list[i] = list[i].Substring(list[i].LastIndexOf("\\") + 1);
            }

            return list;
        }

        public Data.ProjectDataSet RetriveSprintDefaultItems(string projectCategory)
        {
            // read the project from the XML template file
            Data.ProjectDataSet dataset = new Data.ProjectDataSet();
            dataset.EnforceConstraints = false;
            dataset.ReadXml(ServerPath + "\\App_Data\\ProjectTemplates\\" + projectCategory + "\\SprintData.xml");
            return dataset;
        }

        public Data.ProjectDataSet RetriveBacklogItemUnits()
        {
            Data.ProjectDataSet dataset = new BadHabit.Factory.Data.ProjectDataSet();
            dataset.EnforceConstraints = false;
            this.backlogItemUnitTA.FillDistinct(dataset.BacklogItemUnit);
            return dataset;
        }

        /// <summary>
        /// Retrives the project template.
        /// </summary>
        /// <param name="templatePath">Path where the template files are stored</param>
        /// <returns>Template</returns>
        public Data.ProjectDataSet RetriveProjectTemplate(string templatePath)
        {
            // read the project from the XML template file
            Data.ProjectDataSet project = new Data.ProjectDataSet();
            project.ReadXml(templatePath + "\\ProjectData.xml");

            // Fix the project Number
            project.Project[0].ProjectNumber = this.NextProjectNumber();

            // Fix the estimated start date
            project.Project[0].EstimatedStartDate = DateTime.Today;

            // ok, now we need to fix the Guid ids            
            string projectUId = Guid.NewGuid().ToString().ToLower();
            project.EnforceConstraints = false;

            foreach (Data.ProjectDataSet.ProjectRow r in project.Project.Rows)
            {
                r.ProjectUId = projectUId;
            }

            foreach (Data.ProjectDataSet.SprintRow r in project.Sprint.Rows)
            {
                r.SprintUId = Guid.NewGuid().ToString().ToLower();
                r.ExpirationDate = DateTime.Now.AddDays(31);
                r.CreateDate = DateTime.Now;
            }

            foreach (Data.ProjectDataSet.BacklogItemRow r in project.BacklogItem.Rows)
            {
                r.BacklogItemUId = Guid.NewGuid().ToString().ToLower();
            }

            foreach (Data.ProjectDataSet.BacklogItemHoursRow r in project.BacklogItemHours.Rows)
            {
                r.BacklogItemHoursUId = Guid.NewGuid().ToString().ToLower();
            }

            project.Project[0].CreateDate = DateTime.Now;

            if (project.Project[0].HourBankMode == (short)HourBankMode.NOT_BANKPROJECT)
            {
                Data.ProjectDataSet sprint = this.RetriveSprintDefaultItems(project.Project[0].Category);
                project.Project[0].AddNewSprint(sprint);
            }

            project.EnforceConstraints = true;

            return project;
        }

        /// <summary>
        /// Retrives the proposal template.
        /// </summary>
        /// <param name="templatePath">Path where the template files are stored</param>
        /// <returns>Template</returns>
        public Data.ProjectDataSet RetriveProposalTemplate(string templatePath)
        {
            // read the project from the XML template file
            Data.ProjectDataSet template = new Data.ProjectDataSet();
            template.EnforceConstraints = false;
            template.ReadXml(templatePath + "\\ProposalData.xml");

            // Fix the create date
            template.Proposal[0].CreateDate = DateTime.Now;

            // ok, now we need to fix the Guid ids            
            string proposalUId = Guid.NewGuid().ToString().ToLower();

            foreach (Data.ProjectDataSet.ProposalRow r in template.Proposal.Rows)
            {
                r.ProposalUId = proposalUId;
            }

            foreach (Data.ProjectDataSet.ProposalObservationRow r in template.ProposalObservation.Rows)
            {
                r.ProposalObservationUId = Guid.NewGuid().ToString().ToLower();
            }

            foreach (Data.ProjectDataSet.ProposalFixedCostItemRow r in template.ProposalFixedCostItem.Rows)
            {
                r.FixedPriceItemUId = Guid.NewGuid().ToString().ToLower();
            }

            return template;
        }

        /// <summary>
        /// Retrives the e-mail that should be send to the client.
        /// </summary>
        /// <param name="project">Project</param>        
        /// <returns>The email body and subject</returns>
        public Data.EmailDataSet RetriveTemplateEmail(string projectUId, string templatePath)
        {
            Data.ProjectDataSet project = this.RetriveProject(projectUId);

            // read the project from the XML template file
            Data.EmailDataSet template = new Data.EmailDataSet();
            template.ReadXml(serverFilePath + ".\\Templates\\" + project.Project[0].Category + "\\" + templatePath);
            template.Email[0].Subject = template.Email[0].Subject.Replace("$ProjectName$", project.Project[0].ProjectName);
            template.Email[0].Subject = template.Email[0].Subject.Replace("$ClientName$", project.Project[0].ClientName);
            template.Email[0].Body = template.Email[0].Body.Replace("$ProjectName$", project.Project[0].ProjectName);
            template.Email[0].Body = template.Email[0].Body.Replace("$ClientName$", project.Project[0].ClientName);

            if (template.Email[0].IsToNull())
            {
                template.Email[0].To = string.Empty;
            }

            template.Email[0].To = this.ProposalDestinataries(project) + template.Email[0].To;

            return template;
        }

        private string ProposalDestinataries(Data.ProjectDataSet project)
        {
            string emails = string.Empty;
            foreach (Data.ProjectDataSet.BacklogItemUnitRow unit in project.BacklogItemUnit.Select("Type=" + (short)TeamRoles.CLIENT_CONTACT))
            {
                foreach (Data.ProjectDataSet.ProjectRoleRow r in project.ProjectRole.Select("UnitName='" + unit.UnitName + "'"))
                {
                    emails = emails + r.ContactEmail + ";";
                }
            }

            return emails;
        }

        public static bool CheckVersion(string version)
        {
            if ("unknow/debug".Equals(version))
            {
                return true;
            }

            if ("factoryTail".Equals(version))
            {
                return true;
            }

            if ("factoryWebSite".Equals(version))
            {
                return true;
            }

            long v = 0;
            long vo = 0;
            try
            {
                v = long.Parse(version.Replace(".", string.Empty));
                vo = long.Parse(Properties.Settings.Default.FactoryClientMinVersion.Replace(".", string.Empty));
            }
            catch
            {
                return false;
            }

            if (v < vo)
            {
                return false;
            }

            return true;
        }

        /// <summary>
        /// Store the project dataset into the data base.
        /// </summary>
        /// <param name="project">project dataset</param>
        public Data.ProjectDataSet SaveProject(Data.ProjectDataSet project)
        {
            UpdateRoleMemberInformation(project);

            Data.ProjectDataSet deletedRows = (Data.ProjectDataSet)project.GetChanges(System.Data.DataRowState.Deleted);
            Data.ProjectDataSet modifiedRows = (Data.ProjectDataSet)project.GetChanges(System.Data.DataRowState.Modified);
            Data.ProjectDataSet addedModifiedRows = (Data.ProjectDataSet)project.GetChanges(System.Data.DataRowState.Added);

            if (modifiedRows != null)
            {
                if (addedModifiedRows == null)
                {
                    addedModifiedRows = modifiedRows;
                }
                else
                {
                    addedModifiedRows.Merge(modifiedRows);
                }
            }

            // child tables deletes
            if (deletedRows != null)
            {
                this.riskTA.Update(deletedRows);

                this.proposalApprovedTA.Update(deletedRows);
                this.proposalItemTA.Update(deletedRows);
                this.proposalFixedCostItemTA.Update(deletedRows);
                this.proposalObservationsTA.Update(deletedRows);

                this.projectPaymentTA.Update(deletedRows);

                this.backlogItemHoursTA.Update(deletedRows);   // scanerio childs

                this.backlogItemTA.Update(deletedRows);     // release childs

                this.proposalTA.Update(deletedRows);    // project childs
                this.sprintTA.Update(deletedRows);
                this.projectRoleTA.Update(deletedRows);
                this.backlogItemUnitTA.Update(deletedRows);

                this.projectTA.Update(deletedRows); // project                
            }

            if (addedModifiedRows != null)
            {
                // parent table updates            
                this.projectTA.Update(addedModifiedRows);

                this.backlogItemUnitTA.Update(addedModifiedRows);

                this.projectRoleTA.Update(addedModifiedRows);

                // did that cuz this thing is nothing working at design time
                addedModifiedRows.BacklogItem.ParentRelations[0].ChildKeyConstraint.AcceptRejectRule = System.Data.AcceptRejectRule.None;

                this.sprintTA.Update(addedModifiedRows);

                this.backlogItemTA.Update(addedModifiedRows);

                this.backlogItemHoursTA.Update(addedModifiedRows);

                this.proposalTA.Update(addedModifiedRows);

                this.proposalItemTA.Update(addedModifiedRows);   // proposal childs  
                this.proposalFixedCostItemTA.Update(addedModifiedRows);
                this.proposalObservationsTA.Update(addedModifiedRows);
                this.proposalApprovedTA.Update(addedModifiedRows);

                this.projectPaymentTA.Update(addedModifiedRows);

                this.riskTA.Update(addedModifiedRows);
            }

            return project;
        }

        /// <summary>
        /// Return the next project number.
        /// </summary>
        /// <returns>next project number</returns>
        public short NextProjectNumber()
        {
            int? num = (int?)this.projectTA.ScalarMaxProjectNumber();
            if (!num.HasValue)
            {
                return 0;
            }

            return (short)(num.Value + 1);
        }

        public Data.ProjectDataSet RetriveProjectWithOutProposal(string projectUId)
        {
            Data.ProjectDataSet project = new BadHabit.Factory.Data.ProjectDataSet();
            this.FillProjectDateSet(projectUId, project, true, true, true, false, true);
            return project;
        }

        public Data.ProjectDataSet RetriveProjectAndRolesOnly(string projectUId)
        {
            Data.ProjectDataSet project = new BadHabit.Factory.Data.ProjectDataSet();
            this.FillProjectDateSet(projectUId, project, true, true, false, false, false);
            return project;
        }

        public Data.ProjectDataSet RetriveProject(string projectUId)
        {
            Data.ProjectDataSet project = new BadHabit.Factory.Data.ProjectDataSet();
            this.FillProjectDateSet(projectUId, project, true, true, true, true, true);
            return project;
        }

        public Data.ProjectDataSet RetriveProject(int projectNumber)
        {
            Data.ProjectDataSet project = new BadHabit.Factory.Data.ProjectDataSet();
            this.projectTA.FillByProjectNumber(project.Project, projectNumber);
            this.FillProjectDateSet(project.Project[0].ProjectUId, project, false, true, true, true, true);
            return project;
        }

        /// <summary>
        /// Fills a project dataset with data from the databae.
        /// </summary>
        /// <param name="projectUId">The projectUId</param>
        /// <param name="project">The dataset project to be filled</param>
        /// <param name="fillProject">True if the project table should be filled</param>
        /// <param name="fillRoles">True if the role table should be filled</param>
        /// <param name="fillBacklog">True if the backlogs tables should be filled</param>
        /// <param name="fillProposal">Thrue if the proposals tables should be filled</param>
        private void FillProjectDateSet(string projectUId, Data.ProjectDataSet project, bool fillProject, bool fillRoles, bool fillBacklog, bool fillProposal, bool fillRisk)
        {
            if (fillProject)
            {
                this.projectTA.FillByProjectUId(project.Project, projectUId);
            }

            if (fillRoles)
            {
                this.backlogItemUnitTA.FillByProjectUId(project.BacklogItemUnit, projectUId);
                this.projectRoleTA.FillByProjectUId(project.ProjectRole, projectUId);
            }

            if (fillBacklog)
            {
                this.sprintTA.FillByProjectUId(project.Sprint, projectUId);
                this.backlogItemTA.FillByProjectUId(project.BacklogItem, projectUId);
                this.backlogItemHoursTA.FillByProjectUId(project.BacklogItemHours, projectUId);
                this.sprintCodeVersionTA.FillByProjectUId(project.SprintCodeVersion, projectUId);
            }

            if (System.Threading.Thread.CurrentPrincipal.IsInRole(TeamRoles.COMMERCIAL_GUY.ToString()))
            {
                if (fillProposal)
                {
                    this.proposalTA.FillByProjectUId(project.Proposal, projectUId);
                    this.projectPaymentTA.FillByProjectUId(project.ProjectPayment, projectUId);

                    foreach (Data.ProjectDataSet.ProposalRow p in project.Proposal)
                    {
                        this.proposalObservationsTA.FillByProposalUId(project.ProposalObservation, p.ProposalUId);
                        this.proposalFixedCostItemTA.FillByProposalUId(project.ProposalFixedCostItem, p.ProposalUId);
                        this.proposalItemTA.FillByProposalUId(project.ProposalItem, p.ProposalUId);
                    }
                }
            }

            if (fillRisk)
            {
                this.riskTA.FillByProjectUId(project.Risk, projectUId);
            }
        }

        /// <summary>
        /// Retrive all projects from the data base.
        /// </summary>        
        /// <returns>project dataset</returns>
        public Data.ProjectDataSet RetriveAllProjects()
        {
            Data.ProjectDataSet project = new BadHabit.Factory.Data.ProjectDataSet();
            this.projectTA.Fill(project.Project);

            return project;
        }

        /// <summary>
        /// Retrive oportunities projects.
        /// </summary>        
        /// <returns>project dataset</returns>
        public Data.ProjectDataSet RetriveOportunitiesProjects()
        {
            Data.ProjectDataSet project = new BadHabit.Factory.Data.ProjectDataSet();
            this.projectTA.FillOportunitiesProjects(project.Project);
            return project;
        }

        /// <summary>
        /// Retrive schdeuled projects.
        /// </summary>        
        /// <returns>project dataset</returns>
        public Data.ProjectDataSet RetriveScheduledProjects()
        {
            Data.ProjectDataSet project = new BadHabit.Factory.Data.ProjectDataSet();
            this.projectTA.FillScheduledProjects(project.Project);
            return project;
        }

        /// <summary>
        /// Retrive running projects.
        /// </summary>        
        /// <returns>project dataset</returns>
        public Data.ProjectDataSet RetriveRunningProjects()
        {
            Data.ProjectDataSet project = new BadHabit.Factory.Data.ProjectDataSet();
            this.projectTA.FillRunningProjects(project.Project);
            return project;
        }

        /// <summary>
        /// Retrive closed projects.
        /// </summary>        
        /// <returns>project dataset</returns>
        public Data.ProjectDataSet RetriveClosedProjects()
        {
            Data.ProjectDataSet project = new BadHabit.Factory.Data.ProjectDataSet();
            this.projectTA.FillClosedProjects(project.Project);
            return project;
        }

        /// <summary>
        /// Retrive still to pay projects.
        /// </summary>        
        /// <returns>project dataset</returns>
        public Data.ProjectDataSet RetriveStillToPayProjects()
        {
            Data.ProjectDataSet project = new BadHabit.Factory.Data.ProjectDataSet();
            this.projectTA.FillStillToPayProjects(project.Project);
            return project;
        }

        /// <summary>
        /// Retrive in debit projects.
        /// </summary>        
        /// <returns>project dataset</returns>
        public Data.ProjectDataSet RetriveInDebitProjects()
        {
            Data.ProjectDataSet project = new BadHabit.Factory.Data.ProjectDataSet();
            this.projectTA.FillInDebitProjects(project.Project);
            return project;
        }

        /// <summary>
        /// Retrive closed projects.
        /// </summary>        
        /// <returns>project dataset</returns>
        public Data.ProjectDataSet RetriveToDoProjects(string userUId)
        {
            Data.ProjectDataSet project = new BadHabit.Factory.Data.ProjectDataSet();
            this.projectTA.FillToDoProjects(project.Project, userUId);
            return project;
        }

        /// <summary>
        /// Retrive projects that the member is into.
        /// </summary>        
        /// <returns>project dataset</returns>
        public Data.ProjectDataSet RetriveTeamMemberProjects(string teamMemberId)
        {
            Data.ProjectDataSet project = new BadHabit.Factory.Data.ProjectDataSet();
            this.projectTA.FillByTeamMember(project.Project, teamMemberId);
            return project;
        }

        /// <summary>
        /// Retrive all projects that can be used as payable from the data base.
        /// </summary>        
        /// <returns>project dataset</returns>
        public Data.ProjectDataSet RetriveAllPayableProjects()
        {
            Data.ProjectDataSet project = new BadHabit.Factory.Data.ProjectDataSet();
            this.projectTA.FillPayableProjects(project.Project);
            return project;
        }

        /// <summary>
        /// Retrive all models from the data base.
        /// </summary>        
        /// <returns>project model datatable</returns>
        public Data.ProjectDataSet RetriveAllProjectModels()
        {
            Data.ProjectDataSet ds = new BadHabit.Factory.Data.ProjectDataSet();
            ds.EnforceConstraints = false;
            ds.ReadXml(ServerPath + "\\App_Data\\ProjectModels.xml");
            return ds;
        }

        /// <summary>
        /// Retrive all plataforms from the data base.
        /// </summary>        
        /// <returns>project plataforms datatable</returns>
        public Data.ProjectDataSet RetriveAllProjectPlataforms()
        {
            Data.ProjectDataSet ds = new BadHabit.Factory.Data.ProjectDataSet();
            ds.ReadXml(ServerPath + "\\App_Data\\ProjectPlataforms.xml");
            return ds;
        }

        /// <summary>
        /// Retrive the factory team velocity for a given month.
        /// </summary>
        /// <param name="date">month</param>
        /// <returns>The velocity for the given month</returns>
        public double RetriveFactoryTeamVelocity()
        {
            object o = this.queriesTA.ScalarFactoryTeamVelocity();
            if (o == null || o == DBNull.Value)
            {
                return 0;
            }

            return (double)o;
        }

        public static void LogWarnning(string message)
        {
            try
            {
                System.IO.StreamWriter file = new StreamWriter(ServerPath + "\\App_Data\\Log\\factoryLog.txt", true);

                file.WriteLine("[" + DateTime.Now + "]: " + message);
                file.WriteLine("--------------------------------------------------------------------------------------");
                file.Close();
            }
            catch
            {
            }
        }

        public static void LogError(Exception e)
        {
            LogError(e, null);
        }

        public static void LogError(Exception e, string friendlyMsg)
        {
            string message = string.Empty;
            if (!string.IsNullOrEmpty(friendlyMsg))
            {
                message = friendlyMsg + "\n";
            }

            if (e != null)
            {
                message = message + e.Message;
            }

            try
            {
                System.IO.StreamWriter file = new StreamWriter(ServerPath + "\\App_Data\\Log\\factoryLog.txt", true);

                file.WriteLine("[" + DateTime.Now + "]: " + message);
                if (e != null)
                {
                    file.WriteLine("Source: " + e.Source);
                    file.WriteLine("Trace: " + e.StackTrace);
                }

                file.WriteLine("--------------------------------------------------------------------------------------");
                file.Close();
            }
            catch
            {
            }
        }

        public Data.ProjectDataSet RetriveBacklogItemSizes()
        {
            Data.ProjectDataSet ds = new BadHabit.Factory.Data.ProjectDataSet();
            ds.ReadXml(ServerPath + "\\App_Data\\BacklogItemSizes.xml");
            return ds;
        }

        public Data.ProjectPerformanceDataSet.ProjectPerformanceRow RetriveProjectPerformanceIndicators(string projectUId)
        {
            Data.ProjectPerformanceDataSet performance = new BadHabit.Factory.Data.ProjectPerformanceDataSet();
            this.performanceTA.FillByProjectUId(performance.ProjectPerformance, projectUId);
            return performance.ProjectPerformance.FindByProjectUId(projectUId);
        }

        public string SourceControlViewUrl
        {
            get
            {
                return Properties.Settings.Default.SourceControlViewUrl;
            }
        }
    }
}
